--[[--

std_projectile = {
	iid = image(*****blar blar blar*******), -- im not gonna write all that stuff xD
	dmg = ("kill" or damage),
	height = (projectile image hieght), -- }
	width = (projectile image width)    -- } Used for collision detection.
	x_inc = (x increment, only if proj_homing.home_to_player == 0 )-- }
	y_inc = (y increment, only if proj_homing.home_to_player == 0 )-- } don't define in here!
	rot, -- I think you know... but dont define in here!
	homing, -- if this is ~= 0 then it will home to the player with id homing. DONT DEFINE HERE!
	speed, -- this is plain obvious and doesnt need an explaination unless you're brazillean. ROFLMAO!
	x, -- }
	y, -- } Don't define these two in the actual projectile definition
	shooter, -- this is set when you shoot the thing
	explode = false, -- set to true or false, explodes when collides with wall or player
	teamkill = false, -- set to true or false, if false, the non-exploding things won't hurt team mates
	name, -- name of projectile so when dudes die you can see like: "Pro UbeRocket Noob" ;D
}

So really, a projectile definition willactually look like this:
projectile = {
	iid = image(***BLA BLA BLA***),
	dmg = "kill",
	height = 15,
	width = 8,
	speed = 
}

--]]--

function doublearray(m,n,k)
    local a, x, y = {}
    for x = 0, m do a[x] = {}
        for y = 0, n do
            a[x][y] = k
        end
    end
    return a
end

projectiles = {{}} -- array to keep track of projectiles

map_array = doublearray(4096,2,false) -- used to store a true/false version of the map, if there is a wall, true, if an obstacle or floor, false.

function init_projectile_map_array() -- place this in a function that is called every map change/round restart/equivalent, please. :)
	for x = 0, map("xsize") do
		for y = 0, map("ysize") do
			if tile(x,y,"wall") then
				map_array[x][y] = true
			else
				map_array[x][y] = false
			end
		end
	end
end

function positive(n) -- lol... :P
	return math.abs(n) == n
end

function distance(x1,y1,x2,y2)
	return math.sqrt((x1-x2)^2 + (y1-y2)^2)
end

function createProjectile(proj,shooter,x,y,rot,speed,target_id) -- See Note 1
	if target_id ~= nil and target_id ~= 0 then
		proj.homing = target_id
	else
		proj.homing = 0
		x_inc = math.cos(math.rad(rot)) * speed
		y_inc = math.sin(math.rad(rot)) * speed
	end
	proj.shooter = shooter
	proj.x = x
	proj.y = y
	proj.rot = rot
	proj.speed = speed
	proj.ccr = (proj.width + proj.height)/2 -- this is a radius to a collision circle
	table.insert(projectiles,proj) -- haz officialzy been added as projektile ^_^
end

function removeProjectile(iid,dmg,rot,pid,shooter,x,y) -- Well... there are no IDs xD
	pid = pid or 0
	for k,v in pairs(projectiles) do -- PAIRS IS ALWAYS FASTER!! REMEMBER THAT!
		if ( v.iid == iid and v.dmg == dmg and v.rot == rot and v.homing == pid and v.shooter == shooter and v.x == x and v.y == y ) then -- Being 100% sure this only takes out the one projectile that we WANT to
			table.remove(projectiles,k)
		end
	end
end

function isProjectileColliding(x,y,radius,explode,shooter,dmg,name)
	for rot = 1, 360 do
		local nextx,nexty = math.cos(math.rad(rot)), math.sin(math.rad(rot))
		if( map_array[math.floor(nextx/32)][math.floor(nexty/32)] ) then
			if explode then
				parse("explosion "..x.." "..y.." 20 100 "..shooter)
			end
			return true
		end
		for _,id in pairs( player(0,"tableliving") ) do -- I swear pairs is faster. On my life. *ARGH* my heart! it feels like its exploding! *dies* ( LuaGod's wrath? )
			if distance(player(id,"x"),player(id,"y"),x,y) <= 10 then
				if explode then
					parse("explosion "..x.." "..y.." 20 100 "..shooter)
				else
					if dmg == "kill" then
						parse("customkill "..shooter.." \""..name"\" "..id)
					else
						parse("sethealth "..id.." "..player(id,"health")-dmg)
					end
				end
			end
		end
	end
end

addhook("ms100","update_projectiles")
function update_projectiles()
	for _,p in pairs(projectiles) do
		local x_inc,y_inc
		local tmpspeed = p.speed
		if p.rot then
			if p.homing and p.homing ~= 0 then
				local tmprot = math.deg(math.atan(( p.x - player(p.homing,"x"))/( p.y - player(p.homing,"y")) ))
				local difrot = tmprot - p.rot
				if( difrot >= 70 ) then p.speed = p.speed/2 end -- slow down when turning sharply!! otherwise the things will just crash into walls and unintended players :/
				if( not positive(difrot) ) then
					if( difrot <= 70 ) then tmpspeed = p.speed/2 end
					if difrot > -20 then
						p.rot = tmprot
					else
						p.rot = p.rot - 20
					end
				else
					if( difrot >= 70 ) then tmpspeed = p.speed/2 end
					if difrot > 20 then
						p.rot = p.rot + 20
					else
						p.rot = tmprot
					end
				end
				x_inc = math.cos(math.rad(tmprot)) * tmpspeed
				y_inc = math.sin(math.rad(tmprot)) * tmpspeed
			else
				x_inc = p.x_inc
				y_inc = p.y_inc
			end
			p.x = p.x + x_inc
			p.y = p.y + y_inc
			if isProjectileColliding(p.x,p.y,p.ccr,p.explode,p.dmg,p.name) then
				removeProjectile(p.iid,p.dmg,p.rot,p.target_id,p.shooter,p.x,p.y)
			end
		end
	end
end




--[[
	NOTES:
	1. proj is a projectile definition like std_projectile, x/y are in px, rot in deg, target_id is a player id, speed is... a speed measurement(?), target_id is the ID of a player
		to chase. But speed must be less than or equal to 32, otherwise the collision detection sometimes wont work..
		Also, shooter is the ID of the player who shot the lazer/rocket.
	
	2. The reason there are so many different arguments to removeProjectile is so that there is no possibility for two projectiles to have the exact same things, so you dont remove
		something you werent supposed to.
]]